// app.js
import Config from './utils/conf.js'
import Kits from './utils/kits.js'
import JSON_BIG from 'json-bigint'
// 13386483737
const CryptoJS = require('crypto-js')
Date.prototype.addDays = function (days) {
  var date = new Date(this.valueOf())
  date.setDate(date.getDate() + days)
  return date
}
Date.prototype.addHours = function (hours) {
  var date = new Date(this.valueOf())
  date.setHours(date.getHours() + hours)
  return date
}
Date.prototype.format = function (fmt) {
  var o = {
    "M+": this.getMonth() + 1, //月份 
    "d+": this.getDate(), //日 
    "H+": this.getHours(), //小时 
    "m+": this.getMinutes(), //分 
    "s+": this.getSeconds(), //秒 
    "q+": Math.floor((this.getMonth() + 3) / 3), //季度 
    "S": this.getMilliseconds() //毫秒 
  }
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length))
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
    }
  }
  return fmt
}
require("./utils/ebus.js") // 导入事件总线，全局定义
App({
  Global: { // 全局数据
    Debug: Config.getConfig().Debug,
    // Debug: false,
    Version: Config.getConfig().Version,
    AppId: Config.getConfig().AppId,
    FddAppId: Config.getConfig().FddAppId,
    Title: Config.getConfig().Title,
    QmapKey: Config.getConfig().QmapKey,
    API: Config.getConfig().API,
    OpenId: '',
    User: {},
    Token: 'Guest',
    Requests: new Set(), // 网络请求对象
    /*ColorUI 配置对象 */
    StatusBar: undefined,
    Custom: undefined,
    CustomBar: undefined
  },

  onLaunch() {
    // ColorUI 获取系统信息
    wx.getSystemInfo({
      success: e => {
        this.Global.StatusBar = e.statusBarHeight
        let capsule = wx.getMenuButtonBoundingClientRect()
        if (capsule) {
          this.Global.Custom = capsule
          this.Global.CustomBar = capsule.bottom + capsule.top - e.statusBarHeight
        } else {
          this.Global.CustomBar = e.statusBarHeight + 50
        }
      }
    })
    // 执行登录
    this.doWxmnLogin(undefined)
    // 检测版本
    Kits.checkVersion()
  },
  onError(msg) {
    console.log(msg)
  },
  /* 自定义方法 */
  // 弹出提示
  doAlert(title, message, fnSucc) {
    wx.showModal({
      title: title,
      showCancel: false,
      content: message,
      confirmText: '知道了',
      success: () => {
        fnSucc && typeof fnSucc === 'function' && fnSucc()
      }
    })
  },
  // 进行小程序登录
  doWxmnLogin(callback) {
    // return
    if (this.login && callback == undefined) {
      return
    }
    this.login = true

    wx.setStorageSync('App.Uid', '')
    wx.setStorageSync('App.Token', 'Guest')
    wx.setStorageSync('App.Name', '')
    wx.setStorageSync('App.User', '{}')
    wx.setStorageSync('App.Users', '[]')

    wx.login({
      success: (res) => {
        this.login = false
        if (res.code) {
          this.doPost({
            uri: '/app/user/account/wxmn/signin',
            body: {
              appid: Config.getConfig().AppId,
              code: res.code
            },
            fnSucc: resp => {
            //  if(resp.data.user[0].name &&resp.data.user[0].merchant.state == 0){
              wx.setStorageSync('App.Users', JSON.stringify(resp.data.users))
              if (wx.getStorageSync('App.Last.Uid') != '') {
                let user = resp.data.users.find(u => u.id == wx.getStorageSync('App.Last.Uid'))
                if (user != undefined) {
                  wx.setStorageSync('App.Uid', user.id)
                  wx.setStorageSync('App.Token', user.token)
                  wx.setStorageSync('App.Name', user.name)
                  wx.setStorageSync('App.User', JSON.stringify(user))
                  this.Global.User = user
                } else if (resp.data.users.length > 0) {
                  wx.setStorageSync('App.Uid', resp.data.users[0].id)
                  wx.setStorageSync('App.Token', resp.data.users[0].token)
                  wx.setStorageSync('App.Name', resp.data.users[0].name)
                  wx.setStorageSync('App.User', JSON.stringify(resp.data.users[0]))
                  this.Global.User = resp.data.users[0]
                }
              } else if (resp.data.users.length > 0) {
                wx.setStorageSync('App.Uid', resp.data.users[0].id)
                wx.setStorageSync('App.Token', resp.data.users[0].token)
                wx.setStorageSync('App.Name', resp.data.users[0].name)
                wx.setStorageSync('App.User', JSON.stringify(resp.data.users[0]))
                this.Global.User = resp.data.users[0]
              }
              this.Global.Token = this.Global.User.token
              this.Global.OpenId = resp.data.openid
              callback && callback.call()
            //  }
            },
            fnFail: resp => {
              wx.setStorageSync('App.Uid', '')
              wx.setStorageSync('App.Token', 'Guest')
              wx.setStorageSync('App.Name', '')
              wx.setStorageSync('App.User', '{}')
              wx.setStorageSync('App.Users', '[]')
              this.Global.User = {}
              this.Global.Token = 'Guest'
              this.doAlert('出错啦', `获取用户信息失败，[${resp.stat.err}] ${resp.stat.msg}`)
            }
          })
        } else {
          this.doAlert('微信服务异常', `小程序登录失败，请重新打开小程序`)
        }
      },
      fail: () => {
        this.login = false
        this.doAlert('微信服务异常', `小程序登录失败，请重新打开小程序`)
      },
    })
  },
  // Loading 
  doShowLoading(reqid) {
    this.Global.Requests.add(reqid)
    setTimeout(() => {
      if (this.Global.Requests.size > 0) {
        wx.showLoading({
          mask: true,
          title: 'loading...',
        })
      }
    }, 300)
  },
  doHideLoading(reqid) {
    if (reqid == 'All') {
      this.Global.Requests.clear()
    } else {
      this.Global.Requests.delete(reqid)
    }
    if (this.Global.Requests.size > 0) {
      return
    }
    wx.hideLoading()
  },
  // 执行网络请求，返回 RequestTask
  doPost({
    uri,
    body,
    noLoading,
    fnSucc,
    fnFail,
    fnComp
  }) {
    let url = this.Global.API + uri
    let bodyStr = JSON.stringify(body || {})
    // 通用参数
    let token = wx.getStorageSync('App.Token') || 'Guest'
    let time = (new Date().getTime() / 1000).toFixed(0)
    let nonce = Kits.randomString()
    let version = '20000'
    let reqid = Kits.getUUID()

    // 加密Body数据（Debug 模式下不加密）
    if (!this.Global.Debug) {
      let key = CryptoJS.MD5(nonce + time).toString()
      let iv = CryptoJS.MD5(key).toString().substring(8, 24)
      let enx = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(bodyStr), CryptoJS.enc.Utf8.parse(key), {
        iv: CryptoJS.enc.Utf8.parse(iv),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7,
      })
      bodyStr = CryptoJS.enc.Base64.stringify(enx.ciphertext)
    }

    // 计算签名
    let sign = CryptoJS.MD5(nonce + bodyStr + reqid).toString()

    // 封装url
    url = url + `?token=${token}&time=${time}&nonce=${nonce}&sign=${sign}&version=${version}&reqid=${reqid}&noaes=${this.Global.Debug ? 'true' : 'false'}`
    if (!noLoading) {
      this.doShowLoading(reqid)
    }
    return wx.request({
      url: url,
      method: 'POST',
      data: bodyStr,
      timeout: 5 * 60 * 1000,
      dataType: 'plain',
      success: (res) => {
        if (res.statusCode != 200) {
          fnFail && typeof fnFail === 'function' ? fnFail({
            stat: {
              err: -1,
              msg: `网络连接失败，代码：[${res.statusCode}]`
            }
          }) : this.doAlert('请求失败', `网络请求出现错误，请稍后重试。代码：[${res.statusCode}]`)

          return
        }
        let plain = res.data
        let resp = {}
        if (plain.startsWith('{') && plain.endsWith('}')) {
          resp = JSON_BIG.parse(plain)
        } else {
          let key = CryptoJS.MD5(time + reqid).toString()
          let iv = CryptoJS.MD5(key).toString().substring(8, 24)

          let decrypt = CryptoJS.AES.decrypt(CryptoJS.enc.Base64.stringify(CryptoJS.enc.Base64.parse(plain)), CryptoJS.enc.Utf8.parse(key), {
            iv: CryptoJS.enc.Utf8.parse(iv),
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
          })
          resp = JSON_BIG.parse(decrypt.toString(CryptoJS.enc.Utf8))
        }
        console.log('Api -> ' + uri, (body || {}), resp)
        if (resp.stat.err == 0) {
          console.log('resp', resp);
          fnSucc && typeof fnSucc === 'function' && fnSucc(resp)
          return
        }
        if (resp.stat.err == 15) {
          wx.setStorageSync('App.Uid', '')
          wx.setStorageSync('App.Token', 'Guest')
          wx.setStorageSync('App.Name', '')
          wx.setStorageSync('App.User', '{}')
          wx.setStorageSync('App.Users', '[]')
          this.Global.User = {}
          this.Global.OpenID = ''


          this.doAlert('登录已失效', `您的账号登录信息已过期，请重新登录`, () => {
            this.doWxmnLogin(() => {
              wx.reLaunch({
                url: '/pages/splash/splash'
              })
            })
          })
          return
        }
        fnFail && typeof fnFail === 'function' ? fnFail(resp) : this.doAlert('请求失败', `[${resp.stat.err}] ${resp.stat.msg}`)
      },
      fail: () => {
        fnFail && typeof fnFail === 'function' ? fnFail({
          stat: {
            err: -1,
            msg: '网络请求失败'
          }
        }) : this.doAlert('请求失败', `您的网络连接好像出现了问题，请检查`)
      },
      complete: () => {
        if (!noLoading) {
          this.doHideLoading(reqid)
        }
        fnComp && typeof fnComp === 'function' && fnComp()
      },
    })
  }
})